﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using CrusadeGmTool.Diagnostics;

namespace CrusadeGmTool.Net
{
    public class ObjectToSerialize<T>
    {
        private T _object;

        public T Object
        {
            get { return _object; }
            set { _object = value; }
        }
    }

   public class EncryptedSerializer<T>
    {
        private ObjectToSerialize<T> _toSerialize;
        byte[] _encryptionKey;
        string _filename;
        Rijndael _encrypter;
        Logger _log;

        public ObjectToSerialize<T> ToSerialize
        {
            get { return _toSerialize; }
            set { _toSerialize = value; }
        }

        public EncryptedSerializer(string key, string filename)
        {
            _toSerialize = new ObjectToSerialize<T>();
            _encrypter = Rijndael.Create();
            
            _log = new Logger(this.GetType());
            PasswordDeriveBytes pw = new PasswordDeriveBytes(key, Encoding.ASCII.GetBytes(" "));
            _log.Info(pw.GetBytes(128 / 8));
            _filename = filename;
            
            _encrypter.KeySize = pw.GetBytes(128).Length;
            _encrypter.Key = pw.GetBytes(128 / 8);
            _encrypter.IV = pw.GetBytes(128 / 8);
        }

        public void Encrypt()
        {
            FileStream _file = new FileStream(_filename, FileMode.OpenOrCreate, FileAccess.Write);   
            CryptoStream cs = new CryptoStream(_file, _encrypter.CreateEncryptor(), CryptoStreamMode.Write);

            try
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(cs, _toSerialize.Object);
            }
            catch (Exception e)
            {
                _log.Warn(e.Message);
            }
            finally
            {
                cs.Close();
                _file.Close();
            }
        }

        public T Decrypt()
        {
            T retval = default(T);
            FileStream _file = new FileStream(_filename, FileMode.Open, FileAccess.Read);
            CryptoStream cs = new CryptoStream(_file, _encrypter.CreateDecryptor(), CryptoStreamMode.Read);

            try
            {
                BinaryFormatter bf = new BinaryFormatter();
                retval = (T)bf.Deserialize(cs);
                _log.Info("Decrypiting servers... OK !");
            }
            catch (Exception e)
            {
                _log.Warn(e.Message);
            }
            finally
            {
                _file.Close();
                cs.Close();
            }
            return retval;
        }
    }
}
